package com.sharemarking.system.service.impl;

import com.sharemarking.system.dto.UserDetailImpl;
import com.sharemarking.system.entity.User;
import com.sharemarking.system.mapper.RoleMapper;
import com.sharemarking.system.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * 用于获取登录用户信息
 * @author song
 *
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
	
	private final String LOGIN_IMAGE_VALIATECODE="LOGIN_IMAGE_VALIDATECODE";
	
	@Autowired
    UserMapper um;
	
	@Autowired
    RoleMapper rm;
	
	@Autowired
	private CacheManager cm;
	
	@Autowired
	private HttpServletRequest request;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		String xRealIp=request.getHeader("X-real-ip");
		String valiCodeParam=request.getParameter("loginValidateCode");
		String reqId=request.getParameter("reqId");
		
		boolean needValidate=false;
		boolean denied=false;
		if(xRealIp!=null) {
			Cache c=cm.getCache(AuthenticationFailureListenerImpl.remoteLoginFailureTimesCacheName);
			ValueWrapper vw=c.get(xRealIp);
			Integer count=vw==null?0:(Integer)vw.get();
			needValidate=count>3;
			denied=count>10;
		}
		
		if(denied) throw new UsernameNotFoundException("客户端请求过于频繁，已锁定，请10分种后重试");
		
		if(needValidate) {
			Cache cacheLoginImageValidatecode=cm.getCache(LOGIN_IMAGE_VALIATECODE);
			ValueWrapper vwImageValidatecode=cacheLoginImageValidatecode.get(reqId);
			String code=null;
			if(vwImageValidatecode!=null) {
				code=(String)vwImageValidatecode.get();
				cacheLoginImageValidatecode.evict(reqId);
			}
			if(code==null || !code.equalsIgnoreCase(valiCodeParam)){
				throw new UsernameNotFoundException("验证码错误");
			}
		}
		
		boolean locked=false;
		Cache c=cm.getCache(AuthenticationFailureListenerImpl.loginFailTimesCacheName);
		ValueWrapper vw=c.get(username);
		if(vw!=null)locked=(Integer)vw.get()>5;
		
		if(locked) {
			User user=new User();
			user.setLoginName(username);
			return new UserDetailImpl(user, new ArrayList<Integer>(0), new ArrayList<Integer>(0), locked);
		}
		
		User user = um.getByLoginName(username);
		if(user==null)throw new UsernameNotFoundException("用户名错误");
		
		List<Integer> roleIds=um.getRoleIdsByUserId(user.getId());
		List<Integer> permissionIds=um.getPermissionIdsByUserId(user.getId());
		for(Integer roleId:roleIds){
			permissionIds.addAll(rm.getPermissionIdsByRoleId(roleId));
		}
		return new UserDetailImpl(user,roleIds,permissionIds,locked);
	}
	
	public static class LoginValidateException extends AuthenticationException {

		private static final long serialVersionUID = 1L;

		public LoginValidateException(String msg) {
			super(msg);
		}
		
	}

}
